import { ref, h, watch, computed, toRefs, toRaw } from 'vue'
import type { PropType, VNode, ComputedRef, Ref, Reactive } from 'vue'
import { Table, Card } from '@arco-design/web-vue'
import type { TableData, TableProps } from '@arco-design/web-vue/es/table/interface'
import tableTool from './tableTool/index.vue'
import { mergeWith, merge, cloneDeep } from 'lodash'
import type { XTableType } from './tableTool'


export type SlotType = {
    [key in string]: (scoped: any) => VNode
}

export default {
    components: {
        Table,
        Card,
        tableTool
    },
    props: {
        tableConfig: {
            type: Object as PropType<XTableType.TablePropsType>,
            default: () => {
                return {}
            }
        },
        tableToolConfig:{
          type:Object as PropType<XTableType.TableToolType>
        }
        /* ... */
    },
    setup(props: { tableConfig: any }, { attrs, slots, emit, expose }: any) {
        let TableRef = ref()

        //渲染table插槽
        let TableSlotComponent: ComputedRef<SlotType> = computed(() => {
            let slotComp: SlotType = {}
            Object.keys(slots).map(slotItemName => {
                slotComp[slotItemName] = scoped => {
                    return h('div', {}, slots[slotItemName]?.(scoped))
                }
            })
            return slotComp
        })

        //渲染table组件
        let TableComponents = computed(() =>
            h(
                Table,
                {
                    ...props.tableConfig,
                    ref: TableRef
                },
                TableSlotComponent.value
            )
        )

        let TableCardComponent = computed(() => {
            return h(
                Card,
                {
                    style: {
                        width: '100%',
                        height: '100%'
                    },
                    headerStyle: {
                        border: 'none',
                        padding: '0px 15px'
                    },
                    bordered: false
                },
                {
                    default: () => TableComponents.value,
                    title: () => {
                        return h(tableTool, {})
                    }
                }
            )
        })

        expose({
            TableRef
        })

        // 返回渲染函数
        return () => h('div', {}, TableCardComponent.value)
    }
}

//自定义选择 解决arcodesign组件的选择或取消选择父级菜单无法获取其id的问题
function selectCheckBox(
    rowKeys: Array<string | number>,
    changeRowKey: string | number,
    record: TableData,
    keyName: string = 'key',
    treeData: Array<TableData>
): Array<string|number> {
    let nowSelectKeys = rowKeys

    if (record.children) {
        if (nowSelectKeys.includes(changeRowKey)) {
            nowSelectKeys.splice(nowSelectKeys.indexOf(changeRowKey), 1)
     
            changeChildrenSelect(changeRowKey, nowSelectKeys, keyName, record.children, false)
        } else {
            nowSelectKeys.push(changeRowKey)
            changeChildrenSelect(changeRowKey, nowSelectKeys, keyName, record.children, true)

        }
    } else {
        if(nowSelectKeys.includes(changeRowKey)){
            nowSelectKeys.splice(nowSelectKeys.indexOf(changeRowKey), 1)
        }else{
            nowSelectKeys.push(changeRowKey)
            //需要把其父级菜单id也同时选上
            let parentIds=getChildrenParentIds(treeData,[],changeRowKey,keyName)
            if(parentIds){
              nowSelectKeys.push(...parentIds)
            }
        }
    }

    //过滤掉重复的id
    nowSelectKeys = nowSelectKeys.filter((item, index) => {
        return nowSelectKeys.indexOf(item) === index
    })

    return nowSelectKeys
}

function  getChildrenParentIds(treeData:Array<TableData>,parentIds:Array<string|number>,changeRowKey:string|number,keyName:string):Array<string|number>|null{
  let curParentIds:Array<string|number>=[]
  treeData.forEach(item=>{
    if(item[keyName]==changeRowKey){
         curParentIds=[...parentIds]
        return 
    }

   if(item.children){
    let Ids=getChildrenParentIds(item.children,[...parentIds,item[keyName]],changeRowKey,keyName)
    if(Ids){
        curParentIds=[...Ids]
        return 
    }
   } 
  })

  if(curParentIds.length>0){
    return curParentIds 
  }
  return null

}

function changeChildrenSelect(
    changeRowKey: string | number,
    nowSelectKeys: Array<string | number>,
    keyName: string,
    childrenTreeData: Array<TableData>,
    isSelected: boolean
) {
    childrenTreeData.forEach(item => {
        if (isSelected) {
         !item.disabled&&nowSelectKeys.push(item[keyName])
        } else {
          let spliceIndex=nowSelectKeys.indexOf(item[keyName])
          spliceIndex!=-1&& nowSelectKeys.splice(spliceIndex, 1)
        }
        if (item.children && item.children.length > 0) {
            changeChildrenSelect(changeRowKey, nowSelectKeys, keyName, item.children, isSelected)
        }
    })
}



export function useTable(
    tableConfig: XTableType.TablePropsType,
    searchTableData: (
        pageSize: number,
        current: number
    ) => Promise<{ total: number; data: TableData[] }>
): [Reactive<XTableType.TablePropsType>, () => Promise<{ total: number; data: TableData[] }>] {
    let defaultTableConfig = {
        'onUpdate:expanded-keys': (e: any) => {
            if ((tableConfigRef.value as any).expandedKeys) {
                ;(tableConfigRef.value as any).expandedKeys = e
            }
        },

        onSelect: (rowKeys: any, rowKey: string | number, record: TableData) => {
            let selectKeys = selectCheckBox(
                cloneDeep(tableConfigRef.value.selectedKeys as Array<string|number>),
                rowKey,
                record,
                tableConfigRef.value.rowKey || 'key',
                cloneDeep(tableConfigRef.value.data)
            )

            if ((tableConfigRef.value as any).selectedKeys) {
                ;(tableConfigRef.value as any).selectedKeys = selectKeys
            }
        },
        pagination: {
            total: 50,
            current: 1,
            pageSize: 10,
            'onUpdate:current': (e: number) => {
                tableConfigRef.value.pagination.current = e
            },
            'onUpdate:pageSize': (e: number) => {
                tableConfigRef.value.pagination.pageSize = e
            }
        }
    }

    let tableConfigRef = ref(merge(defaultTableConfig, tableConfig))

    if (tableConfigRef.value.pagination?.pageSize && tableConfigRef.value.pagination?.current) {
        watch(
            () => [
                tableConfigRef.value.pagination?.pageSize,
                tableConfigRef.value.pagination?.current
            ],
            (newVal, oldVal) => {
                let current = newVal[1]
                let pageSize = newVal[0]
                getTableData()
            }
        )
    }

    function getTableData() {
        return searchTableData(
            tableConfigRef.value.pagination?.pageSize || 10000,
            tableConfigRef.value.pagination?.current || 1
        ).then((res: { total: number; data: TableData[] }) => {
            tableConfigRef.value.pagination.total = res.total
            tableConfigRef.value.data = res.data
            return res
        })
    }

    return [tableConfigRef.value, getTableData]
}
